package com.acmedcare.framework.exchange.center.core.integration;

import com.acmedcare.framework.exchange.center.core.PluginMetadata;
import com.acmedcare.framework.exchange.center.core.exception.PluginNotFoundException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.springframework.boot.loader.JarLauncher;
import org.springframework.boot.loader.archive.Archive;
import org.springframework.boot.loader.archive.ExplodedArchive;
import org.springframework.util.FileCopyUtils;

public class SpringBootLauncher extends JarLauncher {

  private PluginMetadata metadata;

  protected SpringBootLauncher(Archive archive, PluginMetadata metadata) {
    super(archive);
    this.metadata = metadata;
  }

  @Override
  protected void launch(String[] args) throws Exception {
    org.springframework.boot.loader.jar.JarFile.registerUrlProtocolHandler();
    ClassLoader classLoader = this.createClassLoader(this.getClassPathArchives());
    metadata.setClassLoader(classLoader);
    this.launch(args, this.getMainClass(), classLoader);
  }

  public static void init(String jarUri, PluginMetadata metadata) throws Exception {
    File jarRoot = new File(jarUri);
    if (!jarRoot.exists()) {

      throw new PluginNotFoundException(String.format("插件Url:%s，不存在！请确认是否加载!", jarUri));
    }

    new SpringBootLauncher(new ExplodedArchive(explode(jarRoot, metadata)), metadata)
        .launch(new String[0]);
  }

  protected static File explode(File archive, PluginMetadata metadata) throws IOException {
    File exploded = new File(String.format("./.temp/%s/jars", metadata.getName()), "exploded");
    if (exploded.exists()) {
      exploded.delete();
    }

    exploded.mkdirs();
    JarFile jarFile = new JarFile(archive);
    Enumeration<JarEntry> entries = jarFile.entries();
    while (entries.hasMoreElements()) {
      JarEntry entry = entries.nextElement();
      File entryFile = new File(exploded, entry.getName());
      if (entry.isDirectory()) {
        entryFile.mkdirs();
      } else {
        FileCopyUtils.copy(jarFile.getInputStream(entry), new FileOutputStream(entryFile));
      }
    }
    jarFile.close();
    return exploded;
  }
}